package com.eksframework.commons.core.choice;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 选择消费，类似if-elseif-else，如if(){}[elseif(){}elseif(){}...]else{}
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-09-27 16:23
 */
public class ChoiceSingle<T> implements Selector, Completer {

    /**
     * a object value
     */
    private final T value;

    /**
     * whether the condition is selectable，The value is true when executed
     */
    private boolean selected;

    /**
     * If the method "otherwise" is executed, the value is true
     */
    private boolean completed;

    /**
     * 是否已选择
     *
     * @return boolean
     */
    @Override
    public boolean isSelected() {
        return selected;
    }

    /**
     * 是否已完成
     *
     * @return boolean
     */
    @Override
    public boolean isCompleted() {
        return completed;
    }

    /**
     * Constructs an instance with the value.
     *
     * @param value The parameter object
     */
    private ChoiceSingle(T value) {
        this.value = value;
        this.selected = false;
        this.completed = false;
    }

    /**
     * 实例化Choose对象
     *
     * @param value The parameter object
     * @param <T>   the class of the value
     * @return The instance
     */
    public static <T> ChoiceSingle<T> of(T value) {
        return new ChoiceSingle<>(value);
    }

    /**
     * 设置条件
     *
     * @param condition 条件
     * @return The instance
     */
    public ChoiceSingle<T> when(boolean condition) {
        if(condition){
            this.selected = true;
        }
        return this;
    }

    /**
     * 设置条件
     *
     * @param predicate 条件
     * @return The instance
     */
    public ChoiceSingle<T> when(Predicate<? super T> predicate) {
        if (Objects.nonNull(predicate)) {
            this.selected = isSelected() || predicate.test(value);
        }
        return this;
    }

    /**
     * 符合条件则进行执行消费
     *
     * @param consumer 消费
     * @return The instance
     */
    public ChoiceSingle<T> then(Consumer<? super T> consumer) {
        if (this.completed || nonSelected()) {
            return this;
        }
        this.completed = true;
        if (Objects.nonNull(consumer)) {
            consumer.accept(value);
        }
        return this;
    }

    /**
     * 符合当前条件则进行抛出异常
     *
     * @param supplier 异常结果
     * @return The instance
     */
    public <X extends Throwable> ChoiceSingle<T> thenThrow(Supplier<? extends X> supplier) throws X {
        if (this.completed || nonSelected()) {
            return this;
        }
        this.completed = true;
        if (Objects.nonNull(supplier)) {
            throw supplier.get();
        }
        return this;
    }

    /**
     * 没有符合条件时则进行执行消费，该代码必须放到when之后
     *
     * @param consumer 消费
     * @return The instance
     */
    public ChoiceSingle<T> otherwise(Consumer<? super T> consumer) {
        if (this.completed) {
            return this;
        }
        this.completed = true;
        if (Objects.nonNull(consumer) && nonSelected()) {
            consumer.accept(value);
        }
        return this;
    }

    /**
     * 没有符合条件时则进行抛出异常，该代码必须放到when之后
     *
     * @param supplier 异常结果
     * @return The instance
     */
    public <X extends Throwable> ChoiceSingle<T> otherwiseThrow(
            Supplier<? extends X> supplier) throws X {
        if (this.completed) {
            return this;
        }
        this.completed = true;
        if (Objects.nonNull(supplier) && nonSelected()) {
            throw supplier.get();
        }
        return this;
    }

    /**
     * 把值转换为Optional<T>
     *
     * @return Optional
     */
    public Optional<T> optional() {
        return Optional.ofNullable(value);
    }
}
